import pymysql, pickle
from pymysql.connections import Connection
from django.core.cache.backends.base import BaseCache
from rediscluster import RedisCluster
import logging, traceback
from django.core.cache.backends.base import DEFAULT_TIMEOUT

class _Connection(Connection):
    def autocommit(self, value):
        self.autocommit_mode = bool(value)
        self._send_autocommit_mode()

#https://github.com/PyMySQL/PyMySQL/blob/master/pymysql/__init__.py#112
pymysql.Connect = pymysql.connect = pymysql.Connection =_Connection

pymysql.install_as_MySQLdb()

logger = logging.getLogger('django')

#redis集群cache
class RedisClusterCache(BaseCache):
    def __init__(self, server, params):
        super().__init__(params)
        self._server = server
        self._params = params
        self._client = None

    @property
    def client(self):
        if self._client is None:
            max_connections = self._params.get('OPTIONS', {}).get('max_connections', 10)
            connect_timeout = self._params.get('OPTIONS', {}).get('connect_timeout', 3)
            socket_timeout = self._params.get('OPTIONS', {}).get('socket_timeout', 3)

            self._client = RedisCluster(
                    startup_nodes=self._server, max_connections=int(max_connections),
                    socket_connect_timeout=connect_timeout, socket_timeout=socket_timeout
            )

        return self._client

    def set(self, key, value, timeout=DEFAULT_TIMEOUT, **kwargs):
        value = pickle.dumps(value)
        rkey = self.make_key(key)
        return self.client.set(rkey, value, timeout)

    def add(self, key, value, timeout=DEFAULT_TIMEOUT, **kwargs):
        return self.set(key, value, timeout, **kwargs)

    def get(self, key, default=None, **kwargs):
        rkey = self.make_key(key)
        value = self.client.get(rkey)
        if value is None:
            return default

        try:
            value = pickle.loads(value)
        except:
            logger.error(traceback.format_exc())

        return value

    def delete(self, key, **kwargs):
        rkey = self.make_key(key)
        self.client.delete(rkey, **kwargs)
        return True

    def touch(self, key, timeout=DEFAULT_TIMEOUT, **kwargs):
        return self.client.touch(key, **kwargs)

    def close(self, **kwargs):
        self.client.close(**kwargs)

    def incr(self, key):
        rkey = self.make_key(key)
        return self.client.incr(rkey)

    def decr(self, key):
        rkey = self.make_key(key)
        return self.client.decr(rkey)

    def keys(self, key, **kwargs):
        rkey = self.make_key(key)
        return self.client.scan_iter(rkey, **kwargs)

    def iter_keys(self, key, **kwargs):
        return self.keys(key, **kwargs)

    def ttl(self, *args, **kwargs):
        return self.client.ttl(*args, **kwargs)

    def expire(self, key, timeout=DEFAULT_TIMEOUT):
        rkey = self.make_key(key)
        return self.client.expire(rkey, timeout)

    def clear(self):
        pass


